package com.boot2.core.utils;

import org.apache.commons.collections4.EnumerationUtils;

import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zhangweilin
 * @description:FIFOmap,假设key为自增
 * @date 2018/6/27
 */
public class FIFOConcurrentHashMap<V> extends ConcurrentHashMap<String, V> {

    /**
     * 固定的大小
     */
    private int fixSize;

    /**
     * 活跃大小，它的值，随当前线程池活跃数量而上下浮动
     */
    private int activeSize;

    public FIFOConcurrentHashMap(int fixSize) {
        this.fixSize = fixSize;
        this.activeSize = fixSize;
    }

    /**
     * @param key
     * @param value
     * @param minSize 此为当前活跃大小， 当前map是一个fifo相对比较固定大小的一个队列map，但是考虑到当前执行线程活跃的队列可能比较长，并且长度不定，
     *                有可能超过当前固定大小，此时需要调整当前固定大小，以自增5的方式扩容。如果当前活跃队列小于原始固定大小了，则固定大小调回原来设定的值
     *                即保证此map大小，总是在未完成调度任务数量上下徘徊
     *                PS:当前活跃大小指暂未结束的数量
     *
     * @return
     */
    public synchronized V put(String key, V value, int minSize) {

        //先减后加，保证能容下所有活跃的队列
        while (minSize < activeSize && activeSize >= fixSize) {
            activeSize -= 5;
        }

        //        如果当前中活跃大小超越当前map可活跃大小,一直加到能容下所有活跃队列为止
        while (minSize >= activeSize) {
            activeSize += 5;
        }
        return put(key, value);
    }

    @Override
    public synchronized V put(String key, V value) {
        int size = this.size();
        if (size >= activeSize) {
            Enumeration<String> keys = this.keys();
            //FIFO,把最小的key从队列中优先去除
            List<String> keylist = EnumerationUtils.toList(keys);
            String keyStr = Collections.min(keylist);
            Object removedObject = remove(keyStr);
            System.out.println(" FIFOConcurrentHashMap中移除  " + removedObject);
        }
        return super.put(key, value);
    }
}
